package br.com.merks.controller;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.List;

import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import br.com.merks.Util;
import br.com.merks.controller.component.SecurityModule;
import br.com.merks.controller.vo.MarketInfoVO;
import br.com.merks.model.Market;
import br.com.merks.model.MarketAnswer;
import br.com.merks.model.OptionType;
import br.com.merks.model.Trade;
import br.com.merks.service.MarketService;
import br.com.merks.service.TradeService;
import br.com.merks.service.exception.InsufficientFundsException;
import br.com.merks.service.exception.InsufficientMerksException;

@Resource
public class TradeController {
	private Result result = null;
	private TradeService tradeService = null;
	private MarketService marketService = null;
	private SecurityModule loginHandler = null;
	public TradeController(SecurityModule loginHandler, TradeService tradeService, MarketService marketService, Result result) {
		this.result = result;
		this.tradeService = tradeService;
		this.loginHandler = loginHandler;
		this.marketService = marketService;
	}
	
	@Path("/trade/calculate/{option}/{market.id}/{marketAnswer.id}")
	public void calculate(String option, Market market, MarketAnswer marketAnswer) {
		
		Trade trade = new Trade();
		trade.setMarketAnswerId(marketAnswer.getId());
		trade.setMarketId(market.getId());
		this.result.include("currentPrice",this.tradeService.getCurrentPrice(market, marketAnswer));
		this.result.include("trade",trade);
		List<MarketAnswer> answers = this.marketService.findAnswersByMarket(market);
		this.result.include("answersMap", Util.toMap(answers));
		this.result.include("option", option);
		this.result.include("url", "/trade/" + option);
	}
	@Path(priority=1,value="/trade/calculate/{option}/{market.id}/{marketAnswer.id}/{trade.value}")
	public void calculate(String option, Market market, MarketAnswer marketAnswer,Trade trade) {
		trade.setValue(Math.abs(trade.getValue()));
		
		if (option.equals("buy")) {
			trade.setOption(OptionType.buy);
		} else {
			trade.setValue(trade.getValue()-(trade.getValue()*2));
			trade.setOption(OptionType.sell);
		} 
		trade.setMarketAnswerId(marketAnswer.getId());
		trade.setMarketId(market.getId());
		
		BigDecimal currentPrice = this.tradeService.getCurrentPrice(market, marketAnswer);
		BigDecimal afterPrice  = this.tradeService.getAfterPrice(market, marketAnswer,trade) ;
		BigDecimal cost = this.tradeService.getTotalCost(market, marketAnswer,trade);
		BigDecimal userAccount = loginHandler.getUser().getMerks().subtract(this.tradeService.getTotalCost(market, marketAnswer,trade) );
	
		this.result.include("url", "/trade/" + trade.getOption().toString());
		this.result.include("currentPrice",currentPrice);
		this.result.include("afterPrice",afterPrice);
		
		
		this.result.include("cost", cost.abs());
		
		
		
		this.result.include("userAccountability",userAccount);
		List<MarketAnswer> answers = this.marketService.findAnswersByMarket(market);
		this.result.include("answersMap", Util.toMap(answers));
		this.result.include("option", option);
		trade.setValue(Math.abs(trade.getValue()));
		this.result.include("trade", trade);
	}
	@Path(priority=2,value="/trade/{trade.marketId}")
	public void trade(Trade trade) {
		Market market = new Market();
		market.setId(trade.getMarketId());
		List<MarketAnswer> answers = this.marketService.findAnswersByMarket(market);
		this.result.include("answersMap", Util.toMap(answers));
		
		MarketInfoVO mInfo = this.tradeService.getMarketUserTradeInfo(market,this.loginHandler.getUser());
		
		this.result.include("userTradeInfo",mInfo);

	}
	@Path(priority=1,value="/trade/buy/{trade.marketId}/{trade.marketAnswerId}/{trade.value}")
	public void buy(Trade trade) {
		
		trade.setUserId(this.loginHandler.getUser().getId());
		trade.setOption(OptionType.buy);
		trade.setTimestamp(Calendar.getInstance().getTime());
		trade.setValue(Math.abs(trade.getValue()));
		try {
			this.tradeService.buy(trade,loginHandler.getUser());
			this.result.include("buy","ok");
		} catch (InsufficientFundsException e) {
			this.result.include("buy","insufficientfunds");
		}
	}
	@Path(priority=1,value="/trade/sell/{trade.marketId}/{trade.marketAnswerId}/{trade.value}")
	public void sell(Trade trade) {
		trade.setUserId(this.loginHandler.getUser().getId());
		trade.setOption(OptionType.sell);
		trade.setTimestamp(Calendar.getInstance().getTime());
		trade.setValue( Math.abs(trade.getValue())-(Math.abs(trade.getValue())*2) );
		try {
			this.tradeService.sell(trade, loginHandler.getUser());
		} catch (InsufficientMerksException e) {
			this.result.include("sell","insufficientmerks");
		}
	}
	@Path(priority=1,value="/trade/history/{trade.marketId}")
	public void tradeHistory(Trade trade) {
		Market market = new Market();
		market.setId(trade.getMarketId());
		List<MarketAnswer> answers = this.marketService.findAnswersByMarket(market);
		this.result.include("answersMap", Util.toMap(answers));
		this.result.include("report",this.tradeService.tradeHistory(trade));
	}
}
